package top.infopub.job.quartz.core;


import java.text.ParseException;

import org.apache.commons.lang3.time.DateUtils;
import org.quartz.CronExpression;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import top.infopub.util.DateUtil;


/**
 * Quartz核心操作
 * @author Awoke
 * @version 2018年9月20日
 * @see QuartzCoreManager
 * @since
 */
public final class QuartzCoreManager {

    private static final Logger log = LoggerFactory.getLogger(QuartzCoreManager.class);

    /**
     * 启动所有调度
     * @throws SchedulerException 
     * @see
     */
    public static void startScheduler()
        throws SchedulerException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();
    }

    /**
     * 关闭所有调度
     * @throws SchedulerException 
     * @see
     */
    public static void stopScheduler()
        throws SchedulerException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // waitForJobsToComplete=false 不等任务执行完就立即停止
        scheduler.shutdown(true);
    }

    /**
     * 新增job
     * @param jobName  job名称
     * @param jobClass  <font color=red>job相关的业务类，由调用方自实现</font>
     * @param triggerName 触发器名称
     * @param cronExp  cron表达式
     * @param data  业务数据
     * @throws SchedulerException
     * @throws ParseException 
     * @see
     */
    public static void addJob(String jobName, Class<?> jobClass, String triggerName,
                              String cronExp, String data)
        throws SchedulerException, ParseException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // Initiate JobDetail with job name, job group, and executable job class
        JobDetail jobDetail = new JobDetail(jobName, "DEFAULT", jobClass);
        // 传参
        jobDetail.getJobDataMap().put("data", data);
        // Initiate CronTrigger with its name and group name
        CronTrigger cronTrigger = new CronTrigger(triggerName, "DEFAULT");
        // setup CronExpression
        CronExpression cexp = new CronExpression(cronExp);
        // Assign the CronExpression to CronTrigger
        cronTrigger.setCronExpression(cexp);
        // schedule a job with JobDetail and Trigger
        scheduler.scheduleJob(jobDetail, cronTrigger);

        log.info("addJob-->[jobName=" + jobName + "],[jobBean=" + jobClass.getName()
                 + "],[triggerName=" + triggerName + "],[cron=" + cronExp + "],[data=" + data
                 + "]");
        // start the scheduler
        scheduler.start();
    }

    /**
     * 新增只执行一次的job
     * @param jobName  job名称
     * @param jobClass  <font color=red>job相关的业务类，由调用方自实现</font>
     * @param triggerName 触发器名称
     * @param fireTime  执行时间
     * @param data  业务数据
     * @throws SchedulerException
     * @throws ParseException 
     * @see
     */
    public static void addOneTimeJob(String jobName, Class<?> jobClass, String triggerName,
                                     String fireTime, String data)
        throws SchedulerException, ParseException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // Initiate JobDetail with job name, job group, and executable job class
        JobDetail jobDetail = new JobDetail(jobName, "DEFAULT", jobClass);
        // 传参
        jobDetail.getJobDataMap().put("data", data);
        // 创建Trigger对象 
        SimpleTrigger trigger = new SimpleTrigger();
        trigger.setName(triggerName);
        trigger.setGroup("DEFAULT");
        trigger.setStartTime(DateUtils.parseDate(fireTime,
            new String[] {DateUtil.DATE_STYLE_BASIC}));
        // schedule a job with JobDetail and Trigger
        scheduler.scheduleJob(jobDetail, trigger);

        log.info("addOneTimeJob-->[jobName=" + jobName + "],[jobBean=" + jobClass.getName()
                 + "],[triggerName=" + triggerName + "],[fireTime=" + fireTime + "],[data=" + data
                 + "]");
        // start the scheduler
        scheduler.start();
    }

    /**  
     * 修改job执行时间  
     * @param jobDetail  
     * @param cronExp  
     * @throws SchedulerException  
     * @throws ParseException  
     */
    public static void rescheduleJob(String triggerName, String jobName, String cronExp)
        throws SchedulerException, ParseException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // 得到trigger 
        CronTrigger trigger = (CronTrigger)scheduler.getTrigger(triggerName, "DEFAULT");
        // 设置trigger的时间规则 
        trigger.setCronExpression(cronExp);

        log.info("rescheduleJob-->[triggerName=" + triggerName + "],[cronExp=" + cronExp + "]");
        // 重置job 
        scheduler.rescheduleJob(triggerName, "DEFAULT", trigger);
        // 这里为了解决cron下一次执行时间显示错误的问题，先暂停再启用 by Awoke 2018-10-24
        pauseJob(triggerName, jobName);
        resumeJob(triggerName, jobName);
    }

    /**  
     * 修改oneTime_job执行时间  
     * @param jobDetail  
     * @param cronExp  
     * @throws SchedulerException  
     * @throws ParseException  
     */
    public static void rescheduleOneTimeJob(String triggerName, String fireTime)
        throws SchedulerException, ParseException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // 得到trigger 
        SimpleTrigger trigger = (SimpleTrigger)scheduler.getTrigger(triggerName, "DEFAULT");
        // 设置trigger的时间规则 
        trigger.setStartTime(DateUtils.parseDate(fireTime,
            new String[] {DateUtil.DATE_STYLE_BASIC}));

        log.info("rescheduleJob-->[triggerName=" + triggerName + "],[fireTime=" + fireTime + "]");
        // 重置job 
        scheduler.rescheduleJob(triggerName, "DEFAULT", trigger);
    }

    /**
     * 删除job
     * @param triggerName 触发器名称
     * @param jobName  job名称
     * @return
     * @throws SchedulerException 
     * @see
     */
    public static boolean deleteJob(String triggerName, String jobName)
        throws SchedulerException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // pauseTrigger 
        scheduler.pauseTrigger(triggerName, "DEFAULT");
        // deleteJob  
        scheduler.deleteJob(jobName, "DEFAULT");
        // unscheduleJob  
        return scheduler.unscheduleJob(triggerName, "DEFAULT");
    }

    /**
     * 暂停job
     * @param triggerName
     * @param jobName
     * @throws SchedulerException 
     * @see
     */
    public static void pauseJob(String triggerName, String jobName)
        throws SchedulerException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // pauseTrigger  
        scheduler.pauseTrigger(triggerName, "DEFAULT");
        // pauseJob
        scheduler.pauseJob(jobName, "DEFAULT");
    }

    /**
     * 恢复job
     * @param triggerName
     * @param jobName
     * @throws SchedulerException 
     * @see
     */
    public static void resumeJob(String triggerName, String jobName)
        throws SchedulerException {
        // Initiate a Schedule Factory
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        // Retrieve a scheduler from schedule factory
        Scheduler scheduler = schedulerFactory.getScheduler();
        // resumeTrigger
        scheduler.resumeTrigger(triggerName, "DEFAULT");
        // resumeJob
        scheduler.resumeJob(jobName, "DEFAULT");
    }

}
